// storage helpers with expiration mechanism
// default expiration time: 3600 seconds (1 hour)
const DEFAULT_EXPIRATION_TIME = 3600; // 3600 seconds

/**
 * StorageData class for managing expiration-based storage
 */
class StorageData {
    constructor(value, expirationTimeInSeconds = DEFAULT_EXPIRATION_TIME) {
        this.value = value;
        this.timestamp = Date.now();
        this.expiration = this.timestamp + (expirationTimeInSeconds * 1000); // Convert seconds to milliseconds
    }

    /**
     * Check if the data is expired
     * @returns {boolean} - True if expired
     */
    isExpired() {
        return Date.now() > this.expiration;
    }

    /**
     * Get remaining time in milliseconds
     * @returns {number} - Remaining time in milliseconds, 0 if expired
     */
    getRemainingTime() {
        const remaining = this.expiration - Date.now();
        return remaining > 0 ? remaining : 0;
    }

    /**
     * Get detailed info about the storage data
     * @returns {object} - {value, timestamp, expiration, isExpired, remainingTime}
     */
    getInfo() {
        const isExpired = this.isExpired();
        return {
            value: this.value,
            timestamp: this.timestamp,
            expiration: this.expiration,
            isExpired: isExpired,
            remainingTime: this.getRemainingTime()
        };
    }

    /**
     * Create StorageData from existing data object
     * @param {object} data - Existing storage data object
     * @returns {StorageData|null} - StorageData instance or null if invalid
     */
    static fromObject(data) {
        if (data && typeof data === 'object' &&
            data.hasOwnProperty('value') &&
            data.hasOwnProperty('timestamp') &&
            data.hasOwnProperty('expiration')) {
            const storageData = new StorageData(data.value, 0);
            storageData.timestamp = data.timestamp;
            storageData.expiration = data.expiration;
            return storageData;
        }
        return null;
    }

    /**
     * Check if an object is a valid StorageData object
     * @param {any} obj - Object to check
     * @returns {boolean} - True if valid StorageData
     */
    static isValid(obj) {
        return obj && typeof obj === 'object' &&
            obj.hasOwnProperty('value') &&
            obj.hasOwnProperty('timestamp') &&
            obj.hasOwnProperty('expiration');
    }
}

/**
 * Set storage with expiration time
 * @param {string} key - Storage key
 * @param {any} value - Value to store
 * @param {number} expirationTimeInSeconds - Expiration time in seconds (default: 3600 seconds)
 */
export const setStorageWithExpiration = (key, value, expirationTimeInSeconds = DEFAULT_EXPIRATION_TIME) => {
    const storageData = new StorageData(value, expirationTimeInSeconds);
    uni.setStorageSync(key, storageData);
}

// Utility functions for common expiration times
/**
 * Set storage with expiration time in minutes
 * @param {string} key - Storage key
 * @param {any} value - Value to store
 * @param {number} minutes - Expiration time in minutes
 */
export const setStorageMinutes = (key, value, minutes) => {
    setStorageWithExpiration(key, value, minutes * 60);
}

/**
 * Set storage with expiration time in hours
 * @param {string} key - Storage key
 * @param {any} value - Value to store
 * @param {number} hours - Expiration time in hours
 */
export const setStorageHours = (key, value, hours) => {
    setStorageWithExpiration(key, value, hours * 3600);
}

/**
 * Set storage with expiration time in days
 * @param {string} key - Storage key
 * @param {any} value - Value to store
 * @param {number} days - Expiration time in days
 */
export const setStorageDays = (key, value, days) => {
    setStorageWithExpiration(key, value, days * 86400);
}


/**
 * Check if storage data is expired without removing it
 * @param {string} key - Storage key
 * @returns {boolean} - True if expired or not found
 */
export const isStorageExpired = (key) => {
    try {
        const rawData = uni.getStorageSync(key);

        if (!rawData) {
            return true;
        }

        if (StorageData.isValid(rawData)) {
            const storageData = StorageData.fromObject(rawData);
            return storageData ? storageData.isExpired() : true;
        }

        return true; // Legacy data without expiration
    } catch (error) {
        console.error('Error checking storage expiration:', error);
        return true;
    }
}

/**
 * Get storage data with detailed info (value, timestamp, expiration)
 * @param {string} key - Storage key
 * @returns {object|null} - {value, timestamp, expiration, isExpired, remainingTime} or null
 */
export const getStorageInfo = (key) => {
    try {
        const rawData = uni.getStorageSync(key);

        if (!rawData) {
            return null;
        }

        if (StorageData.isValid(rawData)) {
            const storageData = StorageData.fromObject(rawData);
            return storageData ? storageData.getInfo() : null;
        }

        return null; // Legacy data
    } catch (error) {
        console.error('Error getting storage info:', error);
        return null;
    }
}

/**
 * Set permanent storage - directly calls uni.setStorageSync without expiration wrapper
 * @param {string} key - Storage key
 * @param {any} value - Value to store
 */
export const setPermanent = (key, value) => {
    try {
        uni.setStorageSync(key, value);
    } catch (error) {
        console.error('Error setting permanent storage:', error);
    }
}

/**
 * Unified getStorage interface - handles both expiration and regular storage
 * @param {string} key - Storage key
 * @returns {any|null} - Stored value or null if expired/not found
 */
export const getStorage = (key) => {
    try {
        const rawData = uni.getStorageSync(key);

        if (!rawData) {
            return null;
        }

        // Check if it's expiration-based storage using StorageData class
        if (StorageData.isValid(rawData)) {
            const storageData = StorageData.fromObject(rawData);

            if (storageData && !storageData.isExpired()) {
                return storageData.value;
            } else {
                // Remove expired data
                removeStorage(key);
                return null;
            }
        }

        // Regular storage data (no expiration)
        return rawData;

    } catch (error) {
        console.error('Error getting storage:', error);
        return null;
    }
}

/**
 * Unified removeStorage interface
 * @param {string} key - Storage key
 */
export const removeStorage = (key) => {

    try {
        // Remove main data
        uni.removeStorageSync(key);


    } catch (error) {
        console.error('Error removing storage:', error);
    }
}

// Main storage object
export const storage = {
    // Unified interfaces
    set: setStorageWithExpiration,
    get: getStorage,
    remove: removeStorage,

    // Permanent storage (no expiration)
    setPermanent: setPermanent,

    // Expiration-based methods
    setWithMinuteExpiration: setStorageMinutes,
    setWithHourExpiration: setStorageHours,
    setWithDayExpiration: setStorageDays,
    isExpired: isStorageExpired,
    getInfo: getStorageInfo,
}

// Export StorageData class for advanced usage
export { StorageData };

export default storage;

